#include <my_header.h>
#include "client.h"

sonQueue_t Queue;
void initQueue(sonQueue_t *Queue);

void * Son_get(void * arg)
{
    shareRes_t * share=(shareRes_t *)arg;

func_gets_client(share->fd);
//接受返回值
char ret_worker[1024]={0};
recv(share->fd,&ret_worker,sizeof(ret_worker),0);

if(strcmp(ret_worker,"-1")==0){
        enQueue(&Queue,-2,share->fileName);
        //printf("文件下载失败.");
    }else{
        enQueue(&Queue,2,share->fileName);
        //printf("文件下载成功.");
    }
    return NULL;
}
void * Son_put(void * arg)
{
    shareRes_t * share=(shareRes_t *)arg;
    char *hash_ptr = file_sha1(share->fileName);
    //hash_ptr[strlen(hash_ptr)]='\0';
    strcpy(share->fileName, hash_ptr);
    //memcpy(train.data,hash_ptr,strlen(hash_ptr));

    int length=strlen(share->fileName);
    //client_file_sha1[strlen(client_file_sha1)] = '\0';
    send(share->fd, &length,sizeof(length), 0);
    send(share->fd, share->fileName,length, 0);///发hash

    ////////////////////////////////////////////////////////////
    printf("传输hash完成");
    share->fileName[strcspn(share->fileName,"\n")]='\0';
    func_puts_client(share->fd,share->fileName);
    printf("我是client我传完了文件\n");

    char ret_worker[1024]={0};
    //接受返回值
    recv(share->fd,&ret_worker,sizeof(ret_worker),0);
    int a=strcmp(ret_worker,"-1");
    if(a==0){
        enQueue(&Queue,-1,share->fileName);
        //printf("%s  文件传输失败",share->fileName);
    }else{
        enQueue(&Queue,1,share->fileName);
        //printf("%s  文件传输成功",share->fileName);
    }
    return NULL;
}
int main(int argc,char* argv[])
{   
    //初始化,创建数组
    char user_cin[1024]={0};//储存用户输入信息
    char ret_worker[1024]={0};//接受服务端的工人线程的返回值
    int result;//临时储存,判断是哪个命令
    train_t train;//要发送的结构体
    char user_name[1024] = {0};//存储用户名
    char password[1024] = {0};//存储用户的明文密码
    char salt[1024] = {0};//存储盐值
    char crypt_password[1024] = {0};//存储加密后的密文密码


    //连接客户端
    int sfd=socket(AF_INET,SOCK_STREAM,0);
    struct sockaddr_in addr;
    addr.sin_family=AF_INET;
    addr.sin_port=htons(atoi(argv[2]));
    addr.sin_addr.s_addr=inet_addr(argv[1]);
    int ret_connect=connect(sfd,(struct sockaddr *)&addr,sizeof(addr));
    ERROR_CHECK(ret_connect,-1,"connect filed");
    printf("您好用户，您接入网盘成功\n");
    SYSLOG_PRINTF(LOG_INFO,"用户接入网盘");

    ///////////////////////////////////////////////// 注册登录逻辑

    while (1) {
        printf("用户您好！请问您是选择‘注册(1)’还是‘登录(2)’？");
        bzero(user_cin, sizeof(user_cin));
        fgets(user_cin, sizeof(user_cin), stdin);
        user_cin[strcspn(user_cin, "\n")] = '\0';
        if (strcmp(user_cin, "1") == 0) {
            //用户注册 1
            printf("用户您好！请您进行注册");
            send(sfd, "1", 2, 0);//先发送1代表用户注册
            printf("请输入用户名:");
            bzero(user_name, sizeof(user_name));
            fgets(user_name, sizeof(user_name), stdin);
            printf("user_name=%s\n",user_name);
            user_name[strcspn(user_name, "\n")] = '\0';
            printf("user_name=%s\n",user_name);
            ssize_t sent=send(sfd, user_name, strlen(user_name), 0);
            printf("user_name=%s\n",user_name);
            if (sent == -1) {
                perror("send failed");
                exit(1);
            }
            printf("请输入密码:");
            bzero(password, sizeof(password));
            fgets(password, sizeof(password), stdin);

            send(sfd, password, strlen(password),0);
            sleep(1);//等待服务端生成密文并返回注册信息：成功(0)或者失败(-1)
            recv(sfd, ret_worker, sizeof(ret_worker), 0);
            if (strcmp(ret_worker, "0") == 0) {
                printf("恭喜用户注册成功！\n");
                break;
            } else if(strcmp(ret_worker, "-1") == 0) {
                printf("注册失败，请用户重新注册！\n");
                SYSLOG_PRINTF(LOG_ERR, "用户注册失败");
                continue;
            }

        } else if (strcmp(user_cin, "2") == 0) {
            //用户登录 2
            printf("用户您好！请您进行登录");
            send(sfd, "2", 2, 0);//先发送2代表用户登录
            printf("请输入用户名:");
            bzero(user_name, sizeof(user_name));
            fgets(user_name, sizeof(user_name), stdin);
            send(sfd, user_name, strlen(user_name), 0);
            printf("请输入密码:");
            bzero(password, sizeof(password));
            fgets(password, sizeof(password), stdin);
            send(sfd, user_name, strlen(user_name), 0);
            printf("1\n");
            recv(sfd, salt, sizeof(salt), 0);//接受服务端发过来的salt，用来生成密文crypt
            printf("1\n");
            //char *ptr_crypt = (char *)malloc(sizeof(char));
            char *ptr_crypt = crypt(password, salt);
            strcpy(crypt_password, ptr_crypt);
            //free(ptr_crypt);
            send(sfd, crypt_password, strlen(crypt_password), 0);

            sleep(1);//等待服务端比对密文，返回信息：登录成功(0) 或者失败(-1)
            recv(sfd, ret_worker, sizeof(ret_worker), 0);
            if (strcmp(ret_worker, "0") == 0) {
                printf("恭喜用户登录成功！\n");
                break;
            } else if(strcmp(ret_worker, "-1") == 0) {
                printf("登录失败，请用户重新登录！\n");
                SYSLOG_PRINTF(LOG_ERR, "用户登录失败");
                continue;
            }

        } else {
            //其他异常情况，让用户重新输入
            printf("您输入的格式错误，请重新输入\n");
            SYSLOG_PRINTF(LOG_ERR, "用户输入格式错误");
            continue;
        }

    }

    printf("您好用户，您接入网盘成功\n");
    SYSLOG_PRINTF(LOG_INFO,"用户接入网盘");

    int epfd=epoll_create(1);
    epollAdd(epfd,STDIN_FILENO);
    struct epoll_event readyset;
    printf("目前支持:\n cd \n ls \n puts \n gets\n remove \n pwd \n mkdir\n rmdir\n");
    int quitNum=0;/////30s退出
    while(1)//用户输入命令 对命令字符串切割，解析，并用TLV发送  当使用pwd等需要接受服务器端返回数据的命令，做接受，并打印在屏幕上
    {   
        while(!isEmpty(&Queue)){
            Node_t *nood=Queue.front;
            shareRes_t share;
            if(nood->data==-1){
                printf("%s  文件上传失败!",share.fileName);
            }else if(nood->data==1){
                printf("%s  文件上传成功!",share.fileName);
            }else if(nood->data==-2){
                printf("%s  文件下载失败!",share.fileName);
            }else{
                printf("%s  文件下载成功!",share.fileName);
            }
            deQueue(&Queue);
        }



        int readNum=epoll_wait(epfd,&readyset,1,1000);
        if(readNum==0)printf("请输入需求\n");
        if(readNum==0)
        {
            quitNum++;
            if(quitNum==30)
            {
                printf("服务器将我踢出QAQ\n");
                break;
            }
            continue;
        }
        quitNum=0;    
        read(STDIN_FILENO,user_cin,sizeof(user_cin));
        bzero(user_cin,sizeof(user_cin));
        bzero(ret_worker,sizeof(ret_worker));
        train.flag=0;
        train.length=0;
        bzero(train.data,sizeof(train.data));

        printf("请输入您的需求\n");
        fgets(user_cin,sizeof(user_cin),stdin);
        SYSLOG_PRINTF(LOG_ERR,user_cin);
        char temp[1024]={0};
        strncpy(temp,user_cin,sizeof(temp));
        user_cin[strcspn(user_cin, "\n")] = '\0';
        char *p=strtok(user_cin," ");
        if((result=strcmp(p,"cd"))==0){
            //先把数据存下来
            train.flag=1;
            p=strtok(NULL," ");
            train.length=strlen(p);
            strcpy(train.data,p);

            //检查格式
            p=strtok(NULL," ");
            if(p!=NULL){
                printf("格式错误");
                SYSLOG_PRINTF(LOG_ERR,"格式错误");
                continue;
            }
            //发送小火车
            send(sfd,&train.flag,sizeof(train.flag),0);
            send(sfd,&train.length,sizeof(train.length),0);
            send(sfd,train.data,strlen(train.data),0);
            //接受返回值
            sleep(1);
            recv(sfd,&ret_worker,sizeof(ret_worker),0);

            if(strcmp(ret_worker,"-1")==0){
                printf("cd 失败");
                SYSLOG_PRINTF(LOG_ERR,"cd 失败");
            }
            printf("成功\n");
        }
        else if((result=strcmp(p,"ls"))==0){
            //先把数据存下来
            train.flag=2;
            //p=strtok(NULL," ");
            train.length=strlen(p);
            strcpy(train.data,p);

            //检查格式
            p=strtok(NULL," ");
            if(p!=NULL){
                printf("格式错误");
                SYSLOG_PRINTF(LOG_ERR,"格式错误");
                continue;
            }
            //发送小火车

            send(sfd,&train.flag,sizeof(train.flag),0);
            //send(sfd,&train.length,sizeof(train.length),0);
            //send(sfd,train.data,strlen(train.data),0);
            //接受返回值
            sleep(1);

            recv(sfd,&ret_worker,sizeof(ret_worker),0);

            if(strcmp(ret_worker,"-1")==0){
                printf("ls 失败");
                SYSLOG_PRINTF(LOG_ERR,"ls 失败");
                continue;
            }
            printf("%s\n",ret_worker);
            continue;

        }
        else if((result=strcmp(p,"puts"))==0){
            train.flag=3;
            p=strtok(NULL," ");
            train.length=strlen(p);
            strcpy(train.data,p);
            char file_name[50]={0};
            strcpy(file_name,p);
            //检查格式
            p=strtok(NULL," ");
            if(p!=NULL){
                printf("格式错误");
                SYSLOG_PRINTF(LOG_ERR,"格式错误");
                continue;
            }
            //printf("%s",train.data);
            //发送小火车

            send(sfd,&train.flag,sizeof(train.flag),0);
            send(sfd,&train.length,sizeof(train.length),0);
            send(sfd,train.data,strlen(train.data),0);

            pthread_t thread;
            if (pthread_create(&thread, NULL, Son_get, NULL) != 0) {
                perror("线程创建失败");
                return -1;
            }else{
                printf("您的文件正在上传中,请稍等...");
                continue;
            }
        }
        else if((result=strcmp(p,"gets"))==0){
            train.flag=4;
            p=strtok(NULL," ");
            train.length=strlen(p);
            strcpy(train.data,p);

            //检查格式
            p=strtok(NULL," ");
            if(p!=NULL){
                printf("格式错误");
                SYSLOG_PRINTF(LOG_ERR,"格式错误");
                continue;
            }
            //printf("%s",train.data);
            //发送小火车
            send(sfd,&train.flag,sizeof(train.flag),0);
            send(sfd,&train.length,sizeof(train.length),0);
            send(sfd,train.data,strlen(train.data),0);

            pthread_t thread;
            if (pthread_create(&thread, NULL, Son_put, NULL) != 0) {
                perror("线程创建失败");
                return -1;
            }else{
                printf("您的文件正在下载,请稍后...");
                continue;
            }

        }
        else if((result=strcmp(p,"remove"))==0){
            //先把数据存下来
            train.flag=5;
            p=strtok(NULL," ");
            train.length=strlen(p);
            strcpy(train.data,p);

            //检查格式
            p=strtok(NULL," ");
            if(p!=NULL){
                printf("格式错误");
                SYSLOG_PRINTF(LOG_ERR,"格式错误");
                continue;
            }
            //printf("%s",train.data);
            //发送小火车
            send(sfd,&train.flag,sizeof(train.flag),0);
            send(sfd,&train.length,sizeof(train.length),0);
            send(sfd,train.data,strlen(train.data),0);

            sleep(1);
            //接受返回值
            while(1){
                ssize_t ret=recv(sfd,&ret_worker,sizeof(ret_worker),0);
                if(ret>0){
                    //printf("%ld\n",ret);
                    break;
                }
            }
            int a=strcmp(ret_worker,"-1");
            if(a==0){
                printf("remove 失败");
                SYSLOG_PRINTF(LOG_ERR,"remove 失败");
            }
            continue;

        }
        else if((result=strcmp(p,"pwd"))==0){
            //先把数据存下来
            train.flag=6;
            //p=strtok(NULL," ");
            train.length=strlen(p);
            strcpy(train.data,p);

            //检查格式
            p=strtok(NULL," ");
            if(p!=NULL){
                printf("格式错误");
                SYSLOG_PRINTF(LOG_ERR,"格式错误");
                continue;
            }
            //printf("%s",train.data);
            //发送小火车
            send(sfd,&train.flag,sizeof(train.flag),0);
            send(sfd,&train.length,sizeof(train.length),0);
            send(sfd,train.data,strlen(train.data),0);

            //接受返回值
            while(1){
                ssize_t ret=recv(sfd,&ret_worker,sizeof(ret_worker),0);
                if(ret>0){
                    //printf("%ld\n",ret);
                    break;
                }
            }
            int a=strcmp(ret_worker,"-1");
            if(a==0){
                printf("pwd 失败");
                SYSLOG_PRINTF(LOG_ERR,"pwd 失败");
                continue;
            }
            //处理返回值
            printf("%s\n",ret_worker);
            continue;

        }

        else if((result=strcmp(p,"mkdir"))==0){
            //先把数据存下来
            train.flag=7;
            p=strtok(NULL," ");
            train.length=strlen(p);
            strcpy(train.data,p);

            //检查格式
            p=strtok(NULL," ");
            if(p!=NULL){
                printf("格式错误");
                SYSLOG_PRINTF(LOG_ERR,"格式错误");
                continue;
            }
            //printf("%s",train.data);
            //发送小火车
            send(sfd,&train.flag,sizeof(train.flag),0);
            send(sfd,&train.length,sizeof(train.length),0);
            send(sfd,train.data,strlen(train.data),0);

            //接受返回值
            while(1){
                ssize_t ret=recv(sfd,&ret_worker,sizeof(ret_worker),0);
                //printf("%ld\n",ret);
                if(ret>0){
                    //printf("%ld\n",ret);
                    break;
                }
            }
            printf("%s\n",ret_worker);
            int a=strcmp(ret_worker,"-1");
            if(a==0){
                printf("mkdir 失败");
                SYSLOG_PRINTF(LOG_ERR,"mkdir 失败");
            }
            continue;
        }
        else if((result=strcmp(p,"rmdir"))==0){
            //先把数据存下来
            train.flag=8;
            p=strtok(NULL," ");
            train.length=strlen(p);
            strcpy(train.data,p);

            //检查格式
            p=strtok(NULL," ");
            if(p!=NULL){
                printf("格式错误");
                SYSLOG_PRINTF(LOG_ERR,"格式错误");
                continue;
            }
            //printf("%s",train.data);
            //发送小火车
            send(sfd,&train.flag,sizeof(train.flag),0);
            send(sfd,&train.length,sizeof(train.length),0);
            send(sfd,train.data,strlen(train.data),0);

            //接受返回值
            while(1){
                ssize_t ret=recv(sfd,&ret_worker,sizeof(ret_worker),0);
                if(ret>0){
                    //printf("%ld\n",ret);
                    break;
                }
            }
            int a=strcmp(ret_worker,"-1");
            if(a==0){
                printf("rmdir 失败");
                SYSLOG_PRINTF(LOG_ERR,"redir 失败");
            }
            printf("删除成功\n");
            continue;

        }
        else{
            printf("您输入格式错误，请重新输入\n");
            SYSLOG_PRINTF(LOG_ERR,"用户输入格式错误");
            continue;
        }

    }
    close(sfd);
    return 0;
}